package com.license.logic.pso;

import java.util.ArrayList;
import java.util.List;

import com.license.common.util.Constants;
import com.license.common.util.Utils;
import com.license.logic.alimentation.Alimentation;
import com.license.logic.geneticAlgorithm.common.CommonOperation;
import com.license.logic.preference.Activity;

public class Operation extends CommonOperation{
	
	
	
	public Operation(){
		super();
	}
	
	
//	private JessRecomandation jessRecomandation = new JessRecomandation();
//	private static int numarApel = 0;
	
	public Velocity substractPositions(Position position1, Position position2, int day){
		Velocity result = new Velocity();
		
		Alimentation alimentation = new Alimentation();
		alimentation.setBreakFast(getNewSubstractFoodItem(position1.getAlimentation().getBreakFast(), position2.getAlimentation().getBreakFast(), "breakfast", day % Constants.DIET_NUMBER_GENERATED == 1));
		alimentation.setDinner(getNewSubstractFoodItem(position1.getAlimentation().getDinner(), position2.getAlimentation().getDinner(), "dinner", day % Constants.DIET_NUMBER_GENERATED == 2));
		alimentation.setLunch(getNewSubstractFoodItem(position1.getAlimentation().getLunch(), position2.getAlimentation().getLunch(), "lunch", day % Constants.DIET_NUMBER_GENERATED == 3));
		alimentation.setSnack(getNewSubstractFoodItem(position1.getAlimentation().getSnack(), position2.getAlimentation().getSnack(), "snack", day % Constants.DIET_NUMBER_GENERATED == 4));

		result.setAlimentation(alimentation);
		result.setActivities(getNewSubstractActivity(position1.getActivities(), position2.getActivities(), position1.getWeight()));
		return result;
	}
	
	/**
	 *	addition between two velocities
	 * */	
	public Velocity addVelocities(Velocity velocity1, Velocity velocity2, double particle1ProbabilityDir, double particle2ProbabilityDir){
		
		Velocity result = new Velocity();
		
		List<Activity> newActivities = new ArrayList<Activity>();
		boolean activityFound;
		for( Activity activity1 : velocity1.getActivities()) {
			activityFound = false;
			for( Activity activity2 : velocity2.getActivities()) {
				
				if(activity1.getName().equalsIgnoreCase(activity2.getName())) {
					activityFound = true;
					Activity newActivity;
					if (activity1.getMinutes() == Constants.MUTATION || activity2.getMinutes() == Constants.MUTATION){
						newActivity = this.copyActivity(activity1);
						newActivity.setMinutes(Constants.MUTATION);
					} else {
						newActivity = this.copyActivity(activity1);
						newActivity.setMinutes((int) ((activity1.getMinutes()* particle1ProbabilityDir + activity2.getMinutes() * particle2ProbabilityDir)/(particle1ProbabilityDir + particle2ProbabilityDir)));
					}
					newActivities.add(newActivity);
					break;
				}
			}
			if (!activityFound){
				Activity activity = this.copyActivity(activity1);
				activity.setMinutes(Constants.MUTATION);
				newActivities.add(activity);
			}
		}	
		
		result.setActivities(newActivities);

		Alimentation alimentation = new Alimentation();
		alimentation.setBreakFast(getNewAdditionFoodItem(velocity1.getAlimentation().getBreakFast(), velocity2.getAlimentation().getBreakFast(),particle1ProbabilityDir, particle2ProbabilityDir));
		alimentation.setDinner(getNewAdditionFoodItem(velocity1.getAlimentation().getDinner(), velocity2.getAlimentation().getDinner(),particle1ProbabilityDir, particle2ProbabilityDir));
		alimentation.setLunch(getNewAdditionFoodItem(velocity1.getAlimentation().getLunch(), velocity2.getAlimentation().getLunch(),particle1ProbabilityDir, particle2ProbabilityDir));
		alimentation.setSnack(getNewAdditionFoodItem(velocity1.getAlimentation().getSnack(), velocity2.getAlimentation().getSnack(),particle1ProbabilityDir, particle2ProbabilityDir));
		
		result.setAlimentation(alimentation);
		
		return result;
	}
	
	public Position addVelocityToPosition(Position position, Velocity velocity, int day){
		
		Position result = new Position();	
		List<Activity> newActivities = new ArrayList<Activity>();
		for (int index = 0 ; index < velocity.getActivities().size(); index++){
			Activity newActivity = new Activity();
			newActivity.setName("Golf");
			newActivity.setMinutes(60);
			newActivity.setKalories(51);
			newActivity.setKg(80);
			
			
			if (velocity.getActivities().get(index).getMinutes() == Constants.MUTATION){
				newActivity = this.getRandomActivityCopy(this.preferencedActivities);
				newActivity.setKg(position.getWeight());
				newActivity.setMinutes(utils.generateRandomInt(Constants.MINIM_VALUE_ACTIVITY_DURATION, Constants.MAXIM_VALUE_ACTIVITY_DURATION));
			} else if(!position.getActivities().isEmpty()) {
					if(index < position.getActivities().size() && position.getActivities().get(index) != null)
						newActivity = this.copyActivity(position.getActivities().get(index));
			}
			newActivities.add(newActivity);
		}
		result.setActivities(newActivities);
		
		Alimentation alimentation = new Alimentation();
		alimentation.setBreakFast(getNewAdditionVelocityToPosition(position.getAlimentation().getBreakFast(), velocity.getAlimentation().getBreakFast(), "breakfast", day % Constants.DIET_NUMBER_GENERATED == 1));
		alimentation.setDinner(getNewAdditionVelocityToPosition(position.getAlimentation().getDinner(), velocity.getAlimentation().getDinner(), "dinner", day % Constants.DIET_NUMBER_GENERATED == 2));
		alimentation.setLunch(getNewAdditionVelocityToPosition(position.getAlimentation().getLunch(), velocity.getAlimentation().getLunch(), "lunch", day % Constants.DIET_NUMBER_GENERATED == 3));
		alimentation.setSnack(getNewAdditionVelocityToPosition(position.getAlimentation().getSnack(), velocity.getAlimentation().getSnack(), "snack", day % Constants.DIET_NUMBER_GENERATED == 4));
		result.setAlimentation(alimentation);
		result.setWeight(position.getWeight());
		
		return result;
	}
	
	public Velocity updateVelocity ( Particle particle, int day, Position globalBestPosition, double c1, double c2, double c3){
		Velocity velocity = new Velocity();
		Utils util = new Utils();
		velocity = addVelocities(substractPositions(particle.getLocalBest(), particle.getPosition(), day), substractPositions(globalBestPosition, particle.getPosition(), day), c2 * util.generateRandomDouble(0, 1), c3 * util.generateRandomDouble(0, 1));
		velocity = addVelocities(particle.getVelocity(), velocity ,c1 ,c2);
		
		return velocity;
	}
	
	public Position updatePosition ( Particle particle, int day){
		return addVelocityToPosition(particle.getPosition(), particle.getVelocity(), day);
	}
	
	public Position clonePosition(Position oldPosition){
		Position newPosition = new Position();
		newPosition.setAlimentation(copyAlimentation(oldPosition.getAlimentation()));
		newPosition.setActivities(copyActivities(oldPosition.getActivities()));
		newPosition.setWeight(oldPosition.getWeight());
		return newPosition;
	}
}

	